package com.yxjx.duoxue.utils;

import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.BitmapFactory.Options;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.text.SpannableString;
import android.text.style.StyleSpan;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

import com.handmark.pulltorefresh.library.PullToRefreshScrollView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.assist.ImageSize;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer.RoundedDrawable;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import com.yxjx.duoxue.Config;
import com.yxjx.duoxue.PageLoading;
import com.yxjx.duoxue.R;
import com.yxjx.duoxue.webimage.ImageFileCache;
import com.yxjx.duoxue.webimage.ImageGetFromHttp;
import com.yxjx.duoxue.webimage.ImageMemoryCache;

public class UIHelper {
	
	private static ExecutorService sExecutorService;
	private static DisplayImageOptions sDefaultOptions;
	// stringFromResId#300x400:displayOptions
	private static Hashtable<String, DisplayImageOptions> sDefaultOptionsWithIcon = new Hashtable<String, DisplayImageOptions>();
	private static Hashtable<String, DisplayImageOptions> sDefaultRoundOptionsWithIcon = new Hashtable<String, DisplayImageOptions>();
	private static Hashtable<String, DisplayImageOptions> sDefaultCircleOptionsWithIcon = new Hashtable<String, DisplayImageOptions>();
	// 多维度的default图片cache，每个resId有针对不同大小的缓存
	// eg: {resId1:{200x200:drawable1,300x200:drawable2},resId2:...}
	private static Hashtable<Integer, Hashtable<String, Drawable>> sDefaultDrawables = new Hashtable<Integer, Hashtable<String,Drawable>>();
	private static Hashtable<Integer, Hashtable<String, RoundedDrawable>> sDefaultRoundDrawables = new Hashtable<Integer, Hashtable<String,RoundedDrawable>>();
	private static Bitmap sDefaultBitmap;
	
	/**
	 * Thread pool used to asyn load images from web, init in UI Thread.
	 */
	public static void init() {
		sExecutorService = Executors.newFixedThreadPool(5);  
	}
	
	/**
	 * Set root's child textView with specified text.
	 * @param root
	 * @param childId
	 * @param text
	 */
	public static void setText(View root, int childId, String text) {
		TextView textview = (TextView) root.findViewById(childId);
		setText(textview, text);
	}
	
	/**
	 * Set textView with specified text
	 * @param textview
	 * @param text
	 */
	public static void setText(TextView textview, String text) {
		if (!isEmpty(text) && text.equalsIgnoreCase("NULL")) {
			text = "暂未录入";
		}
		if (textview != null) {
			textview.setText(text);
			if (textview instanceof EditText) {
				((EditText) textview).setSelection(text == null ? 0 : text.length());
			}
		}
	}
	
	/**
	 * Set root's child textView with specified text res ID.
	 * @param root
	 * @param childId
	 * @param textResId
	 */
	public static void setText(View root, int childId, int textResId) {
		setText(root, childId, root.getResources().getString(textResId));
	}
	
	/**
	 * Set parentId corresponding view's child textView whose id is resId with specified text res.
	 * @param root
	 * @param parentId
	 * @param childId
	 * @param textRes
	 */
	public static void setText(View root, int parentId, int childId, String textRes) {
		View rootView = root.findViewById(parentId);
		if (rootView == null) {
			return;
		}
		setText(rootView, childId, textRes);
	}
	
	/**
	 * set childId's view OnClickListener
	 * @param root
	 * @param childId
	 * @param listener
	 */
	public static void setClickListener(View root, int childId, View.OnClickListener listener) {
		View child = root.findViewById(childId);
		if (child != null) {
			child.setOnClickListener(listener);
		}
	}
	
	/**
	 * Try to get TextView's string content.
	 * @param root
	 * @param childId
	 * @return
	 */
	public static String getText(View root, int childId) {
		View text = root.findViewById(childId);
		if (text instanceof TextView) {
			return ((TextView) text).getText().toString();
		} else {
			return "";
		}
	}
	
	/**
	 * Try to get EditText's string content.
	 * @param root
	 * @param childId
	 * @return
	 */
	public static String getEditText(View root, int childId) {
		View text = root.findViewById(childId);
		if (text instanceof EditText) {
			return (String) ((EditText) text).getText().toString();
		} else {
			return "";
		}
	}
	
	
	/**
	 * Async loading imageview with specified url.
	 * @param imageview
	 * @param url
	 * @deprecated
	 */
	public static void asyncLoadImage1(ImageView imageview, String url) {
		if (isEmpty(url)) {
			return;
		}
		
		if (Config.LOAD_TEST_IMAGE && !isEmpty(url)) {
			url = url.replace("http://file.learnmore.com.cn",
					"http://file.manytu.com");
		}
		
		if (isBitmapCached(imageview.getContext(), url)) {
			imageview.setImageBitmap(getBitmap(imageview.getContext(), url));
			Utils.logd("loading from cache, url = " + url);
		} else {
			LoadingImageAsyncTask task = new LoadingImageAsyncTask(imageview, url);
			task.execute(new Object());//
			Utils.logd("loading from web, url = " + url);
		}
	}
	
	// [UIL start]
	// get image display options for UIL lib.
	public static DisplayImageOptions getDefaultImageOptions(int iconId, View imageview) {
		String key = "" + iconId + "#" + imageview.getMeasuredWidth() + "x" + imageview.getMeasuredHeight();
		if (!sDefaultOptionsWithIcon.containsKey(key)) {
			DisplayImageOptions dio = new DisplayImageOptions.Builder()
			.showImageOnLoading(getDefaultDrawable(iconId, imageview))
			.showImageForEmptyUri(getDefaultDrawable(iconId, imageview))
			.showImageOnFail(getDefaultDrawable(iconId, imageview))
			.cacheInMemory(true)
			.cacheOnDisk(true).considerExifParams(true)
			.imageScaleType(ImageScaleType.EXACTLY_STRETCHED)
			.build();
			sDefaultOptionsWithIcon.put(key, dio);
		}
		return sDefaultOptionsWithIcon.get(key);
	}
	
	public static DisplayImageOptions getDefaultCircleImageOptions(int iconId, View view) {
		String key = "" + iconId + "#" + view.getMeasuredWidth() + "x" + view.getMeasuredHeight();
		if (!sDefaultCircleOptionsWithIcon.containsKey(key)) {
			// 获取系统设置的圆角半径
			int roundRadius = view.getResources().getDimensionPixelSize(
					R.dimen.circle_radius);
			DisplayImageOptions options = new DisplayImageOptions.Builder()
					.showImageOnLoading(
							getDefaultDrawable(iconId, view))
					.showImageForEmptyUri(
							getDefaultDrawable(iconId, view))
					.showImageOnFail(
							getDefaultDrawable(iconId, view))
					.cacheInMemory(true).cacheOnDisk(true)
					.considerExifParams(true)
					.displayer(new RoundedBitmapDisplayer(roundRadius))
					.imageScaleType(ImageScaleType.EXACTLY_STRETCHED).build();
			// don't use UIL's round image
			sDefaultCircleOptionsWithIcon.put(key, options);
		}
		return sDefaultCircleOptionsWithIcon.get(key);
	}
	public static DisplayImageOptions getDefaultRoundImageOptions(int iconId, View view) {
		String key = "" + iconId + "#" + view.getMeasuredWidth() + "x" + view.getMeasuredHeight();
		if (!sDefaultRoundOptionsWithIcon.containsKey(key)) {
			// 获取系统设置的圆角半径
			int roundRadius = view.getResources().getDimensionPixelSize(R.dimen.round_radius);
			DisplayImageOptions options = new DisplayImageOptions.Builder()
					.showImageOnLoading(
							getDefaultRoundDrawable(iconId, view))
					.showImageForEmptyUri(
							getDefaultRoundDrawable(iconId, view))
					.showImageOnFail(
							getDefaultRoundDrawable(iconId, view))
					.cacheInMemory(true).cacheOnDisk(true)
					.considerExifParams(true)
					.displayer(new RoundedBitmapDisplayer(roundRadius))
					.imageScaleType(ImageScaleType.EXACTLY_STRETCHED).build();
			// don't use UIL's round image
			sDefaultRoundOptionsWithIcon.put(key, options);
		}
		return sDefaultRoundOptionsWithIcon.get(key);
	}
	
	public static DisplayImageOptions getDefaultImageOptions() {
		if (sDefaultOptions == null) {
			sDefaultOptions = new DisplayImageOptions.Builder()
					.cacheInMemory(true)
					.cacheOnDisk(true).considerExifParams(true)
					.build();
		}
		return sDefaultOptions;
	}
	
	public static void emptyDislpyedImageList() {
		AnimateFirstDisplayListener.displayedImages.clear();
	}
	private static ImageLoadingListener sAnimateFirstListener = new AnimateFirstDisplayListener();

	private static class AnimateFirstDisplayListener extends SimpleImageLoadingListener {

		public static final List<String> displayedImages = Collections.synchronizedList(new LinkedList<String>());

		@Override
		public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
			if (loadedImage != null) {
				ImageView imageView = (ImageView) view;
				boolean firstDisplay = !displayedImages.contains(imageUri);
				if (firstDisplay) {
					FadeInBitmapDisplayer.animate(imageView, 100);
					displayedImages.add(imageUri);
				}
			}
		}
		
	}
	
	/**
	 * Use Universal Image Loader to handle image async loading
	 * @param imageview
	 * @param url
	 * @deprecated
	 */
	public static void asyncLoadImage2(ImageView imageview, String url) {
		ImageLoader.getInstance().displayImage(url, imageview, getDefaultImageOptions(), sAnimateFirstListener);
	}
	
	/**
	 * 将default drawable cache
	 * @param resId
	 * @param view
	 * @return
	 */
	private static Drawable getDefaultDrawable(int resId, View view) {
		Context context = view.getContext();
		String sizes = "" + view.getMeasuredWidth() + "x" + view.getMeasuredHeight();
		Utils.logd("CMMX sizes = " + sizes + ", resId = " + resId);
		if (sDefaultDrawables.containsKey(resId)) {
			Hashtable<String, Drawable> row = sDefaultDrawables.get(resId);
			if (row.containsKey(sizes)) {
				return row.get(sizes);
			} else {
				Drawable drawable = context.getResources().getDrawable(resId);
				row.put(sizes, drawable);
				return row.get(sizes);
			}
		} else {
			Hashtable<String, Drawable> row = new Hashtable<String, Drawable>();
			Drawable drawable = context.getResources().getDrawable(resId);
			row.put(sizes, drawable);
			sDefaultDrawables.put(resId, row);
			return row.get(sizes);
		}
	}
	
	/**
	 * 针对round image，另存一份。
	 * @param resId
	 * @param view
	 * @return
	 */
	private static Drawable getDefaultRoundDrawable(int resId, View view) {
		Context context = view.getContext();
		String sizes = "" + view.getMeasuredWidth() + "x" + view.getMeasuredHeight();
		if (!sDefaultRoundDrawables.containsKey(resId)) {
			Drawable drawable = context.getResources().getDrawable(resId);
			int roundRadius = context.getResources().getDimensionPixelSize(R.dimen.round_radius);
			RoundedDrawable roundDrawable = new RoundedDrawable(
					((BitmapDrawable) drawable).getBitmap(), roundRadius, 0);
			Hashtable<String, RoundedDrawable> row = new Hashtable<String, RoundedDrawable>();
			row.put(sizes, roundDrawable);
			sDefaultRoundDrawables.put(resId, row);
		} else {
			Hashtable<String, RoundedDrawable> row = sDefaultRoundDrawables.get(resId);
			if (!row.containsKey(sizes)) {
				Drawable drawable = context.getResources().getDrawable(resId);
				int roundRadius = context.getResources().getDimensionPixelSize(R.dimen.round_radius);
				RoundedDrawable roundDrawable = new RoundedDrawable(
						((BitmapDrawable) drawable).getBitmap(), roundRadius, 0);
				row.put(sizes, roundDrawable);
			}
		}
		return sDefaultRoundDrawables.get(resId).get(sizes);
	}
	
	/**
	 * Use Universal Image Loader to handle image async loading
	 * and also specified default icon.
	 * @param imageview
	 * @param url
	 */
	public static void asyncLoadImage(ImageView imageview, String url, int defaultIcon) {
		ImageLoader.getInstance().displayImage(url, imageview, getDefaultImageOptions(defaultIcon, imageview), null);
	}
	
	/**
	 * 加载圆角的异步图片加载
	 * @param imageview
	 * @param url
	 * @param defaultIcon
	 */
	public static void asyncLoadRoundImage(ImageView imageview, String url,
			int defaultIcon) {
		ImageLoader.getInstance().displayImage(url, imageview,
				getDefaultRoundImageOptions(defaultIcon, imageview),
				sAnimateFirstListener);
	}
	
	/**
	 * 加载圆形图片
	 * @param imageview
	 * @param url
	 * @param defaultIcon
	 */
	public static void asyncLoadCircleImage(ImageView imageview, String url,
			int defaultIcon) {
		ImageLoader.getInstance().displayImage(url, imageview,
				getDefaultCircleImageOptions(defaultIcon, imageview),
				sAnimateFirstListener);
	}
	
	/**
	 * 加载图像，不用使用displayimage的decode优化，而是只使用其下载功能
	 * @param imageview
	 * @param url
	 * @param defaultIcon
	 * @deprecated
	 */
	public static void asyncLoadRoundImageSpecSize(final ImageView imageview,
			String url, int defaultIcon) {
		ImageSize size= new ImageSize(imageview.getWidth(), imageview.getHeight());
		ImageLoader.getInstance().loadImage(url, size,
				new ImageLoadingListener() {

					@Override
					public void onLoadingCancelled(String arg0, View arg1) {
						
					}

					@Override
					public void onLoadingComplete(String arg0, View arg1,
							Bitmap arg2) {
						imageview.setImageBitmap(arg2);
					}

					@Override
					public void onLoadingFailed(String arg0, View arg1,
							FailReason arg2) {
						
					}

					@Override
					public void onLoadingStarted(String arg0, View arg1) {
						if (sDefaultBitmap == null) {
							Drawable drawable = imageview.getResources().getDrawable(R.drawable.default_icon);
							sDefaultBitmap = ((BitmapDrawable) drawable).getBitmap();
						}
						 imageview.setImageBitmap(sDefaultBitmap);
					}
			
		});
		
	}
	// [UIL end]
	
	
	
	public static boolean isEmpty(String str) {
		if (str == null || str.trim().equals("") || str.trim().equals("null")) {
			return true;
		}
		return false;
	}
	
	/**
	 * AsyncTask used to async load image from memory/file/network, and update
	 * ImageView after loading done.
	 * @author mengmengchen
	 *  too many async task cause background thread hang.
	 */
	static class LoadingImageAsyncTask extends AsyncTask {
		
		private ImageView mImageView;
		private String mUrl;
		private static HashMap<Object, LoadingImageAsyncTask> sImageviewTaskMap = new HashMap<Object, UIHelper.LoadingImageAsyncTask>();
		
		public LoadingImageAsyncTask(ImageView imageview, String url) {
			mImageView = imageview;
			mUrl = url;
			
			// 如果之前该imageView的task已经在执行了，则cancel掉并从cache中remove掉
			if (sImageviewTaskMap.containsKey(mImageView)) {
				LoadingImageAsyncTask task = sImageviewTaskMap.get(mImageView);
				task.cancel(true);
				sImageviewTaskMap.remove(mImageView);
			}
			sImageviewTaskMap.put(mImageView, this);

		}

		@Override
		protected Object doInBackground(Object... arg0) {
			Bitmap bm = getBitmap(mImageView.getContext(), mUrl);
			return bm;
		}
		
		@Override
		protected void onPostExecute(Object result) {
			if (result != null) {
				if (!isCancelled()) {
					mImageView.setImageBitmap((Bitmap) result);
//					mImageView.setBackground(new BitmapDrawable((Bitmap) result));
				}
			}
			sImageviewTaskMap.remove(mImageView);
		}
	}
	
	private static Bitmap getBitmap(Context context, String url) {
		ImageMemoryCache memoryCache = ImageMemoryCache.getInstance(context);
		ImageFileCache fileCache = ImageFileCache.getInstance();
	    // 从内存缓存中获取图片
	    Bitmap result = memoryCache.getBitmapFromCache(url);
	    if (result == null) {
	        // 文件缓存中获取
	        result = fileCache.getImage(url);
	        if (result == null) {
	            // 从网络获取
	            result = ImageGetFromHttp.downloadBitmap(url);
	            if (result != null) {
	                fileCache.saveBitmap(result, url);
	                memoryCache.addBitmapToCache(url, result);
	            }
	        } else {
	            // 添加到内存缓存
	            memoryCache.addBitmapToCache(url, result);
	        }
	    }
	    return result;
	}
	
	private static boolean isBitmapCached(Context context, String url) {
		ImageMemoryCache memoryCache = ImageMemoryCache.getInstance(context);
		ImageFileCache fileCache = ImageFileCache.getInstance();
	    // 从内存缓存中获取图片
	    Bitmap result = memoryCache.getBitmapFromCache(url);
	    if (result == null) {
	        // 文件缓存中获取
	    	return false;
	        //return fileCache.isBitmapExist(url);
	    }
	    return true;
	}
	
	/**
	 * set ImageView's resource
	 * @param root
	 * @param childId
	 * @param resId
	 */
	public static void setDrawable(View root, int childId, int resId) {
		if (root == null) {
			return;
		}
		ImageView imageview = (ImageView) root.findViewById(childId);
		if (imageview != null) {
			imageview.setImageResource(resId);
		}
	}
	
	/**
	 * For tips when check user's input format.
	 * @param arg0
	 * @param text
	 */
	public static void showTips(final View arg0, final String text) {
		arg0.post(new Runnable() {
			
			@Override
			public void run() {
				Toast.makeText(arg0.getContext(), text, Toast.LENGTH_SHORT).show();
			}
		});
	}
	
	/**
	 * For tips when check user's input format.
	 * @param arg0
	 * @param resId
	 */
	public static void showTips(final View arg0, final int resId) {
		showTips(arg0, arg0.getContext().getResources().getString(resId));
	}
	
	/**
	 * Is two string equals
	 * @param str1
	 * @param str2
	 * @return
	 */
	public static boolean isEqual(String str1, String str2) {
		if (str1 == null && str2 == null) {
			return true;
		} else if (str1 != null && str2 != null) {
			return str1.equals(str2);
		}
		return false;
	}
	
	/** 
	 * Scroller scroll to head.
	 * @param activity
	 * @param layoutId
	 */
	public static void resetScroll(final Activity activity, int layoutId) {
		View view = activity.findViewById(layoutId);
		if (view == null) {
			return;
		}
		if (view instanceof ScrollView) {
			final ScrollView scrollView = (ScrollView) view;
			scrollView.post(new Runnable() {
				@Override
				public void run() {
					scrollView.scrollTo(0, 0);
				}
			});
		} else if (view instanceof PullToRefreshScrollView) {
			final PullToRefreshScrollView rootView = (PullToRefreshScrollView) view;
			final ScrollView scrollView = rootView.getRefreshableView();
			scrollView.post(new Runnable() {
				@Override
				public void run() {
					scrollView.scrollTo(0, 0);
				}
			});
		}
	}
	
	public static void requestFocus(View root, int layoutId) {
		View view = root.findViewById(layoutId);
		if (view == null || !(view instanceof EditText)) {
			return;
		}
		final EditText editText = (EditText) view;
		editText.post(new Runnable() {
			@Override
			public void run() {
				editText.requestFocus();
				editText.setSelection(editText.length());
			}
		});
		
	}
	
	/**
	 * Hide IME.
	 * @param view
	 */
	public static void hideIME(View view) {
		if (view == null) {
			return;
		}
		InputMethodManager imm = (InputMethodManager)view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 
		imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
	}
	
	/**
	 * start Activity By Loading progress.
	 */
	public static void LoadingActivity(Context host, Intent extraIntent) {
		Intent intent = new Intent(host, PageLoading.class);
		intent.putExtra(PageLoading.EXTRA_INTENT, extraIntent);
		host.startActivity(intent);
	}
	
	public static int str2Int(String str) {
		if (isEmpty(str)) {
			return 0;
		}
		try {
			int num = Integer.valueOf(str);
			return num;
		} catch (Exception e) {
			Log.d("CMM", "str cast to int error e = " + e);
		}
		return 0;
	}
}
